package gat.application.backgroundUser.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.bitsun.core.common.exception.AppException;
import com.bitsun.core.common.exception.ErrorCode;
import com.bitsun.core.common.persistence.BasePService;
import com.bitsun.core.common.persistence.IPService;
import com.bitsun.core.common.persistence.Pager;
import com.bitsun.core.common.persistence.QueryParamUtils;
import com.google.common.base.CaseFormat;
import gat.application.backgroundUser.RolePermissionsService;
import gat.application.backgroundUser.RoleService;
import gat.application.backgroundUser.UserRoleService;
import gat.common.enums.UserExceptionEnums;
import gat.common.enums.UserRoleStatusEnum;
import gat.common.enums.UserRoleTypeEnum;
import gat.convertor.backgroundUser.RoleReqDtoConvertor;
import gat.convertor.backgroundUser.RoleResDtoConvertor;
import gat.dto.req.backgroundUser.RoleReqDto;
import gat.dto.res.backgroundUser.RoleResDto;
import gat.dto.res.backgroundUser.UserRoleResDto;
import gat.infrastructure.persistence.dao.backgroundUser.PermissionsMapper;
import gat.infrastructure.persistence.dao.backgroundUser.RoleMapper;
import gat.infrastructure.persistence.po.backgroundUser.PermissionsPo;
import gat.infrastructure.persistence.po.backgroundUser.RolePo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 示例表，应用（业务编排）层实现
 *
 * @author: tmac
 * @email: tmac
 */
@Slf4j
@Service("roleAppService")
@Transactional(rollbackFor = Exception.class)
public class RoleServiceImpl implements RoleService {

    @Autowired
    private RoleReqDtoConvertor roleReqDtoConvertor;

    @Autowired
    private RoleResDtoConvertor roleResDtoConvertor;

    @Autowired
    private UserRoleService userRoleService;

    @Autowired
    private RolePermissionsService rolePermissionsService;

    @Autowired
    private PermissionsMapper permissionsMapper;


    private IPService<RolePo> rolePoService;

    @SuppressWarnings("SpringJavaAutowiringInspection")
    public RoleServiceImpl(RoleMapper roleMapper) {
        this.rolePoService = new BasePService(roleMapper);
    }





    @Override
    public RoleResDto save(RoleReqDto reqDto) {
        //先进行查询，查看当前的角色是否存在
        QueryWrapper<RolePo> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(RolePo::getName, reqDto.getName());
        RolePo one = rolePoService.getOne(queryWrapper);
        //当前角色存在，则不允许插入
        if (ObjectUtil.isNotEmpty(one)) {
            throw new AppException(UserExceptionEnums.ROLE_HAVING.getMsg());
        }
        //保存角色信息
        RolePo po = roleReqDtoConvertor.dto2Po(reqDto);
        po.setType(UserRoleTypeEnum.SELF_BUILT_ROLE.getValue());
        rolePoService.save(po);
        RoleResDto resDto = roleResDtoConvertor.po2Dto(po);
        return resDto;
    }

    @Override
    public boolean deleteByIds(String ids) {
        List<Long> idLongList =
                Arrays.asList(ids.split(",")).stream().map(s -> NumberUtils.createLong(s.trim())).collect(Collectors.toList());
        idLongList.forEach(i -> {
            //根据id查看当前角色
            RolePo byId = rolePoService.getById(i);
            //系统角色无法进行删除户
            if (UserRoleTypeEnum.SYSTEM_ROLE.getValue().equals(byId.getType())) {
                throw new AppException(UserExceptionEnums.ROLE_SYSTEM_IS.getMsg());
            }
            //判断当前角色状态是否为启用状态
            if (UserRoleStatusEnum.ENABLE.getValue().equals(byId.getStatus())) {
                //启用状态无法移除
                throw new AppException(UserExceptionEnums.ROLE_STATUS_ON.getMsg());
            }
            List<UserRoleResDto> userRoleResDtoList = userRoleService.getByRoleId(i);
            if (CollectionUtil.isNotEmpty(userRoleResDtoList)) {
                throw new AppException(UserExceptionEnums.ROLE_USER_HAVING.getMsg());
            }
        });
        try {
            return rolePoService.removeByIds(idLongList);
        } catch (Exception e) {
            throw new AppException("参数错误：" + ids, ErrorCode.pc("417"), e);
        }
    }

    @Override
    public RoleResDto getNoChild(Long id) {
        RolePo po = rolePoService.getById(id);
        RoleResDto resDto = roleResDtoConvertor.po2Dto(po);
        ArrayList<Long> list = new ArrayList<>();
        list.add(id);
        //根据id查询当前角色的所有权限id

        // 只查询出没有子节点的id
        List<Long> byRoleId = rolePermissionsService.getByRoleId(list);
        List<Long> returnPid = new ArrayList<>();
        byRoleId.forEach(pId -> {
            List<PermissionsPo> permissionsPos = permissionsMapper.selectList(new LambdaQueryWrapper<PermissionsPo>()
                    .eq(PermissionsPo::getParentId, pId)
            );
            if (CollectionUtil.isEmpty(permissionsPos)) {
                returnPid.add(pId);
            }
        });

        resDto.setPermissionIdList(returnPid);
        return resDto;
    }

    @Override
    public RoleResDto selectOne(Long id) {
        RolePo po = rolePoService.getById(id);
        RoleResDto resDto = roleResDtoConvertor.po2Dto(po);
        ArrayList<Long> list = new ArrayList<>();
        list.add(id);
        //根据id查询当前角色的所有权限id
        List<Long> byRoleId = rolePermissionsService.getByRoleId(list);

        // 只查询出没有子节点的id

        resDto.setPermissionIdList(byRoleId);
        return resDto;
    }

    @Override
    public RoleResDto selectOne(Map<String, Object> params) {
        QueryWrapper queryWrapper = QueryParamUtils.queryWrapper4eq(RolePo::new, params);
        queryWrapper.last(" limit 1");
        RolePo po = rolePoService.getOne(queryWrapper);
        RoleResDto resDto = roleResDtoConvertor.po2Dto(po);
        return resDto;
    }

    @Override
    public boolean updateProps(Long id, Map<String, Object> params) {
        UpdateWrapper<RolePo> updateWrapper = QueryParamUtils.updateWrapper4Map(RolePo::new, id, params);
        return rolePoService.update(new RolePo(), updateWrapper);
    }

    @Override
    public boolean updateProps(Long id, RoleReqDto reqDto) {
        //查看请求是否更改启用状态
        if (ObjectUtil.isNotEmpty(reqDto.getStatus()) && UserRoleStatusEnum.ENABLE_NOT.getValue().equals(reqDto.getStatus())) {
            //查看当前角色是否为系统角色
            RolePo byId = rolePoService.getById(id);
            if (UserRoleTypeEnum.SYSTEM_ROLE.getValue().equals(byId.getType())) {
                throw new AppException(UserExceptionEnums.ROLE_SYSTEM_IS.getMsg());
            }
        }
        RolePo po = roleReqDtoConvertor.dto2Po(reqDto);
        po.setId(id);
        return rolePoService.updateById(po);
    }


    @Override
    public boolean updateAllProps(Long id, RoleReqDto reqDto) {
        UpdateWrapper<RolePo> updateWrapper = Wrappers.update();
        updateWrapper.eq("id", id);
        Field[] fields = RoleReqDto.class.getDeclaredFields();
        Arrays.stream(fields).filter(f -> !Modifier.isStatic(f.getModifiers())).forEach(field -> {
            try {
                PropertyDescriptor propertyDescriptor = new PropertyDescriptor(field.getName(), RoleReqDto.class);
                Method getMethod = propertyDescriptor.getReadMethod();
                String fileNameCamel = getMethod.getName().substring(3);
                String fileNameUnderline = CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, fileNameCamel);
                updateWrapper.set(fileNameUnderline, getMethod.invoke(reqDto));
            } catch (Exception ex) {
                log.warn("属性不存在get方法：" + field.getName(), ex);
            }
        });
        return rolePoService.update(new RolePo(), updateWrapper);
    }


    @Override
    public List<RoleResDto> getByUserId(Long userId) {
        //根据id查询当前用户的角色id
        List<Long> roleIds = userRoleService.selByUserId(userId);
        QueryWrapper<RolePo> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().in(RolePo::getId, roleIds);
        List<RolePo> list = rolePoService.list(queryWrapper);
        List<RoleResDto> roleResDtos = roleResDtoConvertor.poList2DtoList(list);
        return roleResDtos;
    }

    @Override
    public List<RoleResDto> getByRoleIds(List<Long> idLongList) {
        List<RolePo> rolePos = rolePoService.list(new LambdaQueryWrapper<RolePo>()
                .in(RolePo::getId, idLongList));
        return roleResDtoConvertor.poList2DtoList(rolePos);
    }

    @Override
    public Pager<RoleResDto> doPager(RoleReqDto reqDto) {
        Page<RolePo> page =
                new Page<>(Long.parseLong(reqDto.getCurrentPage()), Long.parseLong(reqDto.getPageSize()));
        Page<RolePo> doPage = rolePoService.page(page, new LambdaQueryWrapper<RolePo>()
                .like(ObjectUtil.isNotNull(reqDto.getName()), RolePo::getName, reqDto.getName())
                .eq(ObjectUtil.isNotNull(reqDto.getStatus()), RolePo::getStatus, reqDto.getStatus())
        );
        List<RolePo> records = doPage.getRecords();
        List<RoleResDto> dtos = roleResDtoConvertor.poList2DtoList(records);
        return new Pager<>(dtos, doPage.getTotal(), doPage.getSize(), doPage.getCurrent());
    }

    @Override
    public List<RoleResDto> getEnableRoleList() {
        List<RolePo> rolePoList = rolePoService.list(new LambdaQueryWrapper<RolePo>()
                .eq(RolePo::getStatus, UserRoleStatusEnum.ENABLE.getValue())
        );
        return roleResDtoConvertor.poList2DtoList(rolePoList);
    }
}